#include <reg52.h>  // 包含STC89C52的寄存器定义
#include <intrins.h>
#include "DHT11.h"

sbit DHT11_PIN = P3^7;  // 定义连接DHT11的数据引脚为P1.0

// 延时函数，用于微秒级和毫秒级延时
void Delay_us(unsigned int us) {
    while (us--) {
        // 微调此值以适应实际的时钟频率
        _nop_(); _nop_(); _nop_();
        _nop_(); _nop_(); _nop_();
    }
}

void Delay_ms(unsigned int ms) {
    unsigned int i;
    while (ms--)
        for (i = 0; i < 1000; i++) _nop_();
}

// 初始化DHT11的GPIO引脚
void DHT11_Init() {
    DHT11_PIN = 1;  // 设置数据线为高电平状态
}

// 启动DHT11并检查其响应
unsigned char DHT11_Start() {
    unsigned char response;
    DHT11_PIN = 0;  // 拉低数据线至少18ms
    Delay_ms(18);
    DHT11_PIN = 1;  // 拉高数据线20-40us
    Delay_us(30);

    // 设置为输入检查响应
    DHT11_PIN = 1;
    Delay_us(40);
    if (!DHT11_PIN) {
        Delay_us(80);
        if (DHT11_PIN) response = 1;
    } else {
        response = 0;  // 无响应
    }
    Delay_us(80);
    return response;
}

// 读取一字节的数据
unsigned char DHT11_ReadByte() {
	unsigned char i;
	unsigned char resData = 0;
	for (i = 0; i < 8; i++) {
		while (!DHT11_PIN);  // 等待变为高电平
		Delay_us(30);  // 如果超过30us还是高电平则是'1'，否则是'0'
		if (DHT11_PIN)
				resData |= (1 << (7 - i));
		while (DHT11_PIN);  // 等待变为低电平
	}
	return resData;
}

// 读取温湿度数据
unsigned char DHT11_ReadData(unsigned char *humidity, unsigned char *temperature) {
    unsigned char checksum, sum;
    if (DHT11_Start()) {  // 如果有响应
        unsigned char rh_int = DHT11_ReadByte();
        unsigned char rh_dec = DHT11_ReadByte();
        unsigned char t_int = DHT11_ReadByte();
        unsigned char t_dec = DHT11_ReadByte();
        checksum = DHT11_ReadByte();
        
        sum = rh_int + rh_dec + t_int + t_dec;
        if (sum == checksum) {
            *humidity = rh_int;
            *temperature = t_int;
            return 1;  // 读取成功
        }
    }
    return 0;  // 读取失败
}
